<template>
    <div class="role-list-container">
        <!-- 操作面板 -->
        <div class="option-box">
            <!-- 面包屑导航 -->
            <el-breadcrumb separator="/">
                <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item>权限</el-breadcrumb-item>
                <el-breadcrumb-item>权限列表</el-breadcrumb-item>
            </el-breadcrumb>

            <el-button-group>
                <el-button type="primary" @Click="goToAddRole"><el-icon>
                        <CirclePlusFilled />
                    </el-icon>添加权限</el-button>
                <el-button type="danger" @click="BatchDeleteRole"><el-icon>
                        <RemoveFilled />
                    </el-icon>批量删除</el-button>
            </el-button-group>
        </div>

        <!-- 数据 -->
        <el-table :data="data.tableData" style="width: 100%" border lazy stripe @selection-change="handleSelectionChange">
            <el-table-column type="selection" />
            <el-table-column fixed prop="roleId" label="id" width="80" align="center" />
            <el-table-column prop="roleName" label="权限名称" />
            <el-table-column prop="roleDesc" label="权限描述" />

            <el-table-column label="编辑菜单" width="100" align="center">
                <template #default="scope">
                    <el-button link type="primary" size="small" @click="addRole(scope.row.roleId)">编辑权限</el-button>
                </template>
            </el-table-column>

            <el-table-column label="操作单行" width="120" align="center">
                <template #default="scope">
                    <el-button link type="primary" size="small" @click="editDataDialogHandle(scope.row)">编辑</el-button>

                    <!-- 弹出框 -->
                    <el-popconfirm width="220" confirm-button-text="确定" cancel-button-text="取消" :icon="Message"
                        icon-color="#626AEF" title="确定要删除该行权限吗？" @confirm="deleteOneRoleById(scope.row.roleId)">
                        <template #reference>
                            <el-button link type="danger" size="small">删除</el-button>
                        </template>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>

        <!-- 分页器 -->
        <el-pagination v-model:current-page="data.pageInfo.pageCurrent" v-model:page-size="data.pageInfo.pageSize"
            :page-sizes="[5, 10, 15, 20]" layout="total, sizes, prev, pager, next, jumper" :total="data.pageInfo.total"
            @size-change="handleSizeChange" @current-change="handleCurrentChange" />

        <!-- 编辑角色对话框 -->
        <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="isShowEditDialog" title="编辑用户"
            width="30%" :before-close="handleEdurDiglogClose">
            <el-form ref="ruleEditFormRef" :model="ruleEidtForm" :rules="rules" label-width="80px" class="data-form"
                status-icon>
                <el-form-item label="权限id" prop="roleId">
                    <el-input v-model="ruleEidtForm.roleId" disabled />
                </el-form-item>
                <el-form-item label="权限名称" prop="roleName">
                    <el-input v-model="ruleEidtForm.roleName" />
                </el-form-item>
                <el-form-item label="权限描述" prop="roleDesc">
                    <el-input v-model="ruleEidtForm.roleDesc" />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="submitEditForm(ruleEditFormRef)">提交</el-button>
                    <el-button @click="showList">回到列表</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>

        <!-- 编辑权限菜单 -->
        <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="isShowRoleDialog" title="添加权限"
            width="50%" :before-close="handleEdurRoleDiglogClose">
            <el-tree node-key="menuId" default-expand-all @check="handleCheck" :default-checked-keys="expandedRoleList"
                ref="roleListRef" :data="menuList" show-checkbox :props="roleListProps" />
            <div class="button-group">
                <el-button type="primary" @click="AddRoleForm">修改权限</el-button>
                <el-popconfirm title="确定取消本次修改吗？" @confirm="quitEditRole">
                    <template #reference>
                        <el-button>取消修改</el-button>
                    </template>
                </el-popconfirm>
            </div>
        </el-dialog>
    </div>
</template>
    
<script setup lang='ts'>
// 导入信息
import { ref, reactive, onMounted } from 'vue';
import {
    getRoleListByPage,
    deleteRoleById,
    getAllMenu,
    getRoleMenuByRoleId,
    addRoleMenuByRoleIdAndMenuId,
    removeRoleMenuByRoleIdAndMenuId
} from '@/api/RoleApi';
import { useRouter } from 'vue-router';
import { ElMessage, ElMessageBox, ElTree } from 'element-plus';
import { Message } from '@element-plus/icons-vue';
import { postOneRoleById } from '@/api/RoleApi'
import type { FormInstance, FormRules } from 'element-plus';

interface Role {
    roleId: number
    roleName: string
    roleDesc: string
}

const router = useRouter();

// 动态数据中心
const data = reactive({
    tableData: [], // 表格数据
    pageInfo: {
        pageCurrent: 1,
        pageSize: 5,
        total: 0
    },
    BatchDeleteIdArray: {},
})

// 编辑用户需要用到的动态数据
const ruleEidtForm = reactive({
    roleId: 0,
    roleName: "",
    roleDesc: ""
})

// 所有权限信息
let menuList = reactive([]);


const ruleEditFormRef = ref<FormInstance>()

// 编辑表单验证规则
const rules = reactive<FormRules>({
    roleName: [
        { required: true, message: '请输入权限名称！', trigger: 'blur' },
        { min: 3, max: 30, message: '权限名称必须大于3，小于30！', trigger: 'blur' },
        {
            validator: function (rule, value, callback) {
                //  校验英文的正则
                if (/^[a-zA-Z0-9]+$/.test(value) == false) {
                    callback(new Error("权限名称为数据库字段，请用英文,数字代替！"));
                } else {
                    //校验通过
                    callback();
                }
            }
        }
    ],
    roleDesc: [
        { required: true, message: '请输入权限描述信息！', trigger: 'blur' },
        { min: 3, max: 255, message: '权限名称必须大于3，小于255！', trigger: 'blur' },
    ]
})

// 是否显示编辑用户对话框
const isShowEditDialog = ref(false);
// 首付显示添加权限对话框
const isShowRoleDialog = ref(false);

// 当前用户的已拥有的权限
let expandedRoleList: any = reactive([])

// 编辑tree控件的ref
const roleListRef = ref<InstanceType<typeof ElTree>>()


/**
 * 生命周期
 */
onMounted(() => {
    getRoleList(data.pageInfo.pageCurrent, data.pageInfo.pageSize);
    getAllMenus();
})

/**
 * 分页获取权限信息
 * @param current 
 * @param size 
 */
const getRoleList = async (current: Number, size: Number) => {
    await getRoleListByPage(current, size).then(res => {

        data.tableData = res.data.records;

        data.pageInfo.pageCurrent = res.data.current;
        data.pageInfo.pageSize = res.data.size;
        data.pageInfo.total = res.data.total;

    })
}
/**
 * 改变PageSize
 * @param val 
 */
const handleSizeChange = (val: number) => {
    data.pageInfo.pageSize = val;
    getRoleList(data.pageInfo.pageCurrent, data.pageInfo.pageSize);
}
/**
 * 改变pageCurrent
 * @param val 
 */
const handleCurrentChange = (val: number) => {
    data.pageInfo.pageCurrent = val;
    getRoleList(data.pageInfo.pageCurrent, data.pageInfo.pageSize);
}

/**
 * 添加权限,跳转到添加页面
 */
const goToAddRole = () => {
    router.push('/role/add')
}

/**
 * 表格复选框 选择事件
 * @param val 
 */
const handleSelectionChange = (val: Role[]) => {
    const array: Number[] = []
    val.forEach(item => {
        array.push(item.roleId);
    })

    data.BatchDeleteIdArray = array;
}

/**
 * 批量删除
 */
const BatchDeleteRole = async () => {
    const obj: any = data.BatchDeleteIdArray;

    // 判断需要批量删除的对象是否为空,为空直接跳出方法
    if (JSON.stringify(obj) == "{}") {
        ElMessage({
            message: "请先选择需要批量删除的权限!",
            type: 'warning'
        })
        return
    }

    let flag = true;
    let msg = "";

    // 遍历多选到的选项
    for (const item in obj) {
        await deleteRoleById(obj[item]).then(res => {
            if (res.code == 200) {
                msg = res.msg;
                data.BatchDeleteIdArray = {}
                getRoleList(data.pageInfo.pageCurrent, data.pageInfo.pageSize);
            } else {
                flag = false;
                msg = res.msg;
            }
        })
    }
    // 添加定时器,延迟播报
    setTimeout(() => {
        if (flag) {
            ElMessage({
                message: msg,
                type: 'success'
            })
        } else {
            ElMessage({
                message: msg,
                type: 'error'
            })
        }
    }, 100);
}

/**
 * 根据权限id删除单条权限
 * @param roleId 权限ID
 */
const deleteOneRoleById = async (roleId: Number) => {
    await deleteRoleById(roleId).then(res => {
        if (res.code == 200) {
            ElMessage({
                message: res.msg,
                type: 'success'
            })
            // 刷新列表
            getRoleList(data.pageInfo.pageCurrent, data.pageInfo.pageSize);
        } else {
            ElMessage({
                message: res.msg,
                type: 'error'
            })
        }
    })

}

/**
 * 关闭前的回调，会暂停 Dialog 的关闭. 
 * 回调函数内执行 done 参数方法的时候才是真正关闭对话框的时候.
 * @param done 
 */
const handleEdurDiglogClose = (done: () => void) => {
    ElMessageBox.confirm('确定放弃编辑当前列权限吗？')
        .then(() => {
            done()
        })
        .catch(() => {
            // catch error
        })
}

/**
 * 点击编辑按钮触发的事件
 * 1. 显示对话框
 * 2. 将当前列数据拷贝到FORM中,方便编辑
 */
const editDataDialogHandle = (data: Role) => {
    isShowEditDialog.value = true;
    ruleEidtForm.roleId = data.roleId;
    ruleEidtForm.roleName = data.roleName;
    ruleEidtForm.roleDesc = data.roleDesc;
}

/**
 * 提交表单验证信息
 * @param formEl 
 */
const submitEditForm = async (formEl: FormInstance | undefined) => {
    if (!formEl) return // 如果传入的数据为空,直接返回,不执行接下来的操作
    // 验证正则
    await formEl.validate((valid, fields) => {
        if (valid) {
            // 调用API,执行新增操作
            postOneRoleById(ruleEidtForm).then(res => {
                if (res.code == 200) {
                    ElMessage({
                        message: res.msg,
                        type: 'success'
                    })
                    // 清空数据,方便再次填写
                    ruleEidtForm.roleId = 0;
                    ruleEidtForm.roleName = "";
                    ruleEidtForm.roleDesc = "";
                    // 关闭Dialog
                    isShowEditDialog.value = false;
                    // 刷新数据
                    getRoleList(data.pageInfo.pageCurrent, data.pageInfo.pageSize);
                } else {
                    ElMessage({
                        message: res.msg,
                        type: 'error'
                    })
                }
            })


        } else {
            ElMessage({
                message: "请按照要求完成信息的填写!",
                type: 'error'
            })
        }
    })
}

/**
 * 点击【回到列表】按钮，关闭对话框
 */
const showList = () => {
    isShowEditDialog.value = false;
}

/**
 * 关闭前的回调，会暂停 Dialog 的关闭. 
 * 回调函数内执行 done 参数方法的时候才是真正关闭对话框的时候.
 * @param done 
 */
const handleEdurRoleDiglogClose = (done: () => void) => {
    ElMessageBox.confirm('确定放弃添加权限吗？')
        .then(() => {
            // 清空树形控件内容
            expandedRoleList = []
            roleListRef.value?.setCheckedKeys([]);

            done()
        })
        .catch(() => {
            // catch error
        })
}

/**
* 1.展示所有的菜单
* 2.根据角色id显示已经拥有的权限
* 3.根据角色id添加权限(角色菜单关联表roleId&menuId)
*/

// 树形控件配置
const roleListProps = {
    label: 'menuName',
    children: 'children',
}

/**
 * 获取所有菜单权限
 */
const getAllMenus = async () => {
    await getAllMenu().then(res => {
        menuList = res.data
    })
}


/**
 * 获取用户展开节点
 */
const getExpandedRoleList = async (roleId: Number) => {
    await getRoleMenuByRoleId(roleId).then(res => {
        expandedRoleList = res.data
        // 展示对话框
        isShowRoleDialog.value = true;

        // 
    })
}

let roleIdFromData = ref(0);

let delRoleList: any = reactive([]);

/**
 * 添加【权限】按钮
 */
const addRole = (roleId: number) => {

    // 获取用户已经拥有的权限
    getExpandedRoleList(roleId);

    roleIdFromData.value = roleId
}


// 需要添加权限的树形控件表单Array数据
let treeAddRoleForm: Number[] = reactive([])

/**
 * 树形控件选中项改变事件
 * @param data 
 * @param nodes 
 */
const handleCheck = (data: any, nodes: any) => {
    //清空暂存表单数组，初始化数据
    delRoleList = [];
    // 获取已经选中的所有的控件
    treeAddRoleForm = nodes.checkedKeys
    // 已经被选中的节点 
    let SelectedANodeKeys: any = roleListRef.value?.getCheckedKeys()
    // 遍历所有树节点，获取未被选中的节点Id
    let parentKeys: any = [];
    // 遍历获取所有菜单的id
    menuList.forEach((item: any) => {
        parentKeys.push(item.menuId);
        if (item.children) {
            item.children.forEach((citem: { menuId: any; }) => {
                parentKeys.push(citem.menuId)
            })
        }
    })
    // 调用过滤方法，得到需要删除的数组
    delRoleList = filterHasSameArr(parentKeys, SelectedANodeKeys);
}
// 过滤掉相同部分的数组的方法
const filterHasSameArr = (arr1: number[], arr2: number[]) => {
    return arr1.filter((item) => {
        if (arr2.indexOf(item) < 0) {
            return item;
        }
    });
};

/**
 * 提交添加权限
 */
const AddRoleForm = () => {
    let flag = true;
    // 遍历添加权限
    treeAddRoleForm.forEach(async item => {
        await addRoleMenuByRoleIdAndMenuId(roleIdFromData.value, item).then(res => {
            if (res.code == 200) {
                flag = true;
            }
        })
    })
    // 遍历删除权限
    delRoleList.forEach(async (ritem: Number) => {
        await removeRoleMenuByRoleIdAndMenuId(roleIdFromData.value, ritem).then(res => {
            if (res.code == 200) {
                flag = true;
            }
        })
    })


    // 延迟响应结果，反馈给客户端
    setTimeout(() => {
        if (flag) {
            ElMessage({
                message: "修改权限成功！",
                type: "success"
            })

            isShowRoleDialog.value = false;
        } else {
            ElMessage({
                message: "修改权限失败！",
                type: "error"
            })

            isShowRoleDialog.value = false;
        }
    }, 100)
}

/**
 * 退出编辑按钮
 */
const quitEditRole = () => {

    // 清空树形控件内容
    expandedRoleList = []
    roleListRef.value?.setCheckedKeys([]);
    // 隐藏弹出框
    isShowRoleDialog.value = false;
}

// 是否展示删除权限的对话框
const isShowCancleRoleDialog = ref(false);


/**
 * 删除权限
 * @param roleId 
 */
const delRole = (roleId: number) => {
    console.log(roleId);
    // 显示删除权限对话框
    isShowCancleRoleDialog.value = true;
}



</script>
    
<style scoped lang="less">
// 操作新增和删除
.option-box {
    margin: 5px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

// 数据表
.el-table {
    margin: 10px 0;
}


// 分页
.el-pagination {
    position: absolute;
    right: 30px;
}

.button-group {
    margin-top: 20px;
}
</style>